home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 2
/
Amiga Tools 2.iso
/
tools
/
jade
/
src
/
x11_windows.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-09
|
14KB
|
527 lines
/* x11_windows.c -- Window handling for X11
Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
This file is part of Jade.
Jade is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Jade is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jade; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "jade.h"
#include "jade_protos.h"
#include "revision.h"
#include <string.h>
#include <X11/Xutil.h>
_PR int sys_sleep_vw(VW *);
_PR int sys_unsleep_vw(VW *);
_PR void sys_new_vw(VW *);
_PR void sys_kill_vw(VW *);
_PR void sys_update_dimensions(VW *);
_PR void x11_update_dimensions(VW *, int, int);
_PR Window sys_new_window(VW *, VW *, bool);
_PR void sys_kill_window(VW *);
_PR void sys_activate_win(VW *);
_PR void sys_set_vw_pos(VW *, long, long, long, long);
_PR VW *x11_find_window_view(Window);
_PR int sys_set_font(VW *);
_PR void sys_unset_font(VW *);
_PR void sys_reset_sleep_titles(TX *);
_PR bool sys_get_mouse_pos(POS *, VW *);
_PR void sys_windows_init(void);
#define INPUT_EVENTS ButtonPressMask | ButtonReleaseMask | KeyPressMask \
| ExposureMask | StructureNotifyMask | FocusChangeMask
static XSizeHints size_hints;
static XClassHint class_hints = { "jade", "Editor" };
static XWMHints wm_hints;
/* Let the window-manager handle all iconifying... */
int
sys_sleep_vw(VW *vw)
{
if((vw->vw_Flags & VWFF_SLEEPING) == 0)
{
XIconifyWindow(x11_display, vw->vw_Window, x11_screen);
vw->vw_Flags |= VWFF_SLEEPING;
}
return(TRUE);
}
int
sys_unsleep_vw(VW *vw)
{
if(vw->vw_Flags & VWFF_SLEEPING)
{
/* Does this work?? */
wm_hints.flags |= StateHint;
wm_hints.initial_state = IconicState;
XSetWMHints(x11_display, vw->vw_Window, &wm_hints);
XMapWindow(x11_display, vw->vw_Window);
vw->vw_Flags &= ~VWFF_SLEEPING;
}
return(TRUE);
}
void
sys_new_vw(VW *vw)
{
}
void
sys_kill_vw(VW *vw)
{
}
void
sys_update_dimensions(VW *vw)
{
XWindowAttributes xwa;
XGetWindowAttributes(x11_display, vw->vw_Window, &xwa);
x11_update_dimensions(vw, xwa.width, xwa.height);
}
void
x11_update_dimensions(VW *vw, int width, int height)
{
if(vw->vw_Window && ((vw->vw_Flags & VWFF_SLEEPING) == 0))
{
vw->vw_MessageLineY = height - vw->vw_FontY - 2;
vw->vw_MessageFontY = vw->vw_MessageLineY + 2 + FONT_ASCENT(vw);
vw->vw_XStartPix = 0;
vw->vw_YStartPix = 0;
/*
* only measure *text* area, not where messages go
*/
vw->vw_XEndPix = width;
vw->vw_YEndPix = (vw->vw_MessageLineY - 1);
vw->vw_XWidthPix = vw->vw_XEndPix - vw->vw_XStartPix;
vw->vw_YHeightPix = vw->vw_YEndPix - vw->vw_YStartPix;
vw->vw_FontStart = vw->vw_YStartPix + vw->vw_Font->ascent;
vw->vw_MaxX = (vw->vw_XWidthPix / vw->vw_FontX);
vw->vw_MaxY = (vw->vw_YHeightPix / vw->vw_FontY);
if((vw->vw_XStepRatio <= 0)
|| ((vw->vw_XStep = vw->vw_MaxX / vw->vw_XStepRatio) <= 0))
vw->vw_XStep = 1;
if((vw->vw_YStepRatio <= 0)
|| ((vw->vw_YStep = vw->vw_MaxY / vw->vw_YStepRatio) <= 0))
vw->vw_YStep = 1;
}
}
/*
* The only thing necessary in `vw' is the font stuff (I think)
*/
Window
sys_new_window(VW *oldVW, VW *vw, bool useDefDims)
{
unsigned int x, y, width, height;
Window win;
size_hints.flags = 0;
if(!useDefDims && oldVW)
{
x = y = 0;
width = vw->vw_FontX * oldVW->vw_MaxX;
height = (vw->vw_FontY * (oldVW->vw_MaxY + 1)) + 3;
size_hints.flags |= PPosition | PSize;
}
else
{
if(def_dims[0] != -1)
{
x = def_dims[0];
size_hints.flags |= USPosition;
}
else
x = 0;
if(def_dims[1] != -1)
{
y = def_dims[1];
size_hints.flags |= USPosition;
}
else
y = 0;
if(def_dims[2] != -1)
{
width = def_dims[2];
size_hints.flags |= USSize;
}
else
width = 80;
if(def_dims[3] != -1)
{
height = def_dims[3];
size_hints.flags |= USSize;
}
else
height = 24;
width = vw->vw_FontX * width;
height = (vw->vw_FontY * (height + 1)) + 3;
}
win = XCreateSimpleWindow(x11_display, DefaultRootWindow(x11_display),
x, y, width, height,
1, x11_fore_pixel, x11_back_pixel);
if(win)
{
XGCValues xgcv;
vw->vw_Window = win;
/*
* xgcv.plane_mask = x11_fore_pixel | x11_back_pixel;
*/
xgcv.foreground = x11_fore_pixel;
xgcv.background = x11_back_pixel;
xgcv.line_width = 1;
xgcv.font = vw->vw_Font->fid;
vw->vw_WindowSys.ws_TextFontGC = XCreateGC(x11_display, vw->vw_Window,
GCForeground | GCBackground
| GCLineWidth | GCFont,
&xgcv);
xgcv.foreground = x11_back_pixel;
xgcv.background = x11_fore_pixel;
vw->vw_WindowSys.ws_BlkFontGC = XCreateGC(x11_display, vw->vw_Window,
GCForeground | GCBackground
| GCLineWidth | GCFont,
&xgcv);
size_hints.x = x,
size_hints.y = y,
size_hints.width = width,
size_hints.height = height,
size_hints.base_width = 0;
size_hints.base_height = vw->vw_FontY + 3;
size_hints.width_inc = vw->vw_FontX;
size_hints.height_inc = vw->vw_FontY;
size_hints.min_width = size_hints.base_width + size_hints.width_inc;
size_hints.min_height = size_hints.base_height + size_hints.height_inc;
size_hints.flags |= PMinSize | PResizeInc | PBaseSize;
wm_hints.flags = InputHint | StateHint;
wm_hints.input = True;
wm_hints.initial_state = NormalState;
XSetWMProperties(x11_display, win, NULL, NULL, x11_argv, x11_argc, &size_hints, &wm_hints, &class_hints);
XStoreName(x11_display, win, /* "jade" */ VERSSTRING);
XSetWMProtocols(x11_display, win, &x11_wm_del_win, 1);
XSelectInput(x11_display, win, INPUT_EVENTS);
XMapWindow(x11_display, win);
XDefineCursor(x11_display, win, x11_text_cursor);
return(win);
}
return(FALSE);
}
void
sys_kill_window(VW *vw)
{
XFreeGC(x11_display, vw->vw_WindowSys.ws_BlkFontGC);
XFreeGC(x11_display, vw->vw_WindowSys.ws_TextFontGC);
XDestroyWindow(x11_display, vw->vw_Window);
}
void
sys_activate_win(VW *vw)
{
/* Not sure about all this?? */
XRaiseWindow(x11_display, vw->vw_Window);
XWarpPointer(x11_display, None, vw->vw_Window, 0, 0, 0, 0, 1, 1);
}
void
sys_set_vw_pos(VW *vw, long x, long y, long w, long h)
{
XMoveResizeWindow(x11_display, vw->vw_Window,
(unsigned int)x, (unsigned int)y,
(unsigned int)w, (unsigned int)h);
}
VW *
x11_find_window_view(Window win)
{
VW *vw = view_chain;
while(vw)
{
if(vw->vw_Window == win)
break;
vw = vw->vw_Next;
}
return(vw);
}
int
sys_set_font(VW *vw)
{
XFontStruct *font;
if((font = XLoadQueryFont(x11_display, VSTR(vw->vw_FontName)))
|| (font = XLoadQueryFont(x11_display, DEFAULT_FONT)))
{
if(vw->vw_Font)
XFreeFont(x11_display, vw->vw_Font);
vw->vw_Font = font;
vw->vw_FontX = XTextWidth(font, "M", 1);
vw->vw_FontY = vw->vw_Font->ascent + vw->vw_Font->descent;
if(vw->vw_Window)
{
int w, h;
w = vw->vw_MaxX * vw->vw_FontX;
h = ((vw->vw_MaxY + 1) * vw->vw_FontY) + 3;
XSetFont(x11_display, vw->vw_WindowSys.ws_TextFontGC, font->fid);
XSetFont(x11_display, vw->vw_WindowSys.ws_BlkFontGC, font->fid);
sys_update_dimensions(vw);
size_hints.width = w;
size_hints.height = h;
size_hints.base_width = 0;
size_hints.base_height = vw->vw_FontY + 3;
size_hints.width_inc = vw->vw_FontX;
size_hints.height_inc = vw->vw_FontY;
size_hints.min_width = size_hints.base_width + size_hints.width_inc;
size_hints.min_height = size_hints.base_height + size_hints.height_inc;
size_hints.flags = PResizeInc | PMinSize | PBaseSize;
XSetWMNormalHints(x11_display, vw->vw_Window, &size_hints);
XResizeWindow(x11_display, vw->vw_Window, w, h);
#if 0
vw->vw_DeferRefresh++;
#endif
}
return(TRUE);
}
return(FALSE);
}
void
sys_unset_font(VW *vw)
{
if(vw->vw_Font)
{
XFreeFont(x11_display, vw->vw_Font);
vw->vw_Font = NULL;
}
}
_PR VALUE cmd_set_font(VALUE fontname, VALUE vw);
DEFUN_INT("set-font", cmd_set_font, subr_set_font, (VALUE fontname, VALUE vw), V_Subr2, DOC_set_font, "sFont name: ") /*
::doc:set_font::
set-font FONT-NAME [WINDOW]
FONT-NAME specifies the font to use in WINDOW (or the active one).
Under X11 FONT-NAME is a standard font description, under AmigaDOS it is the
name of the font followed by a dash and then the point size to use (for
example "topaz.font-8" to get an 8-point topaz font).
::end:: */
{
VALUE oldfont;
DECLARE1(fontname, STRINGP);
if(!WINDOWP(vw))
vw = VAL(curr_vw);
oldfont = VWIN(vw)->vw_FontName;
VWIN(vw)->vw_FontName = fontname;
if(sys_set_font(VWIN(vw)))
{
VWIN(vw)->vw_Flags |= VWFF_FORCE_REFRESH;
#if 0
VWIN(vw)->vw_DeferRefresh++;
#endif
return(sym_t);
}
else
{
cmd_signal(sym_error, list_2(MKSTR("Can't open font"), fontname));
VWIN(vw)->vw_FontName = oldfont;
return(NULL);
}
}
void
sys_reset_sleep_titles(TX *tx)
{
}
_PR VALUE cmd_screen_width(void);
DEFUN("screen-width", cmd_screen_width, subr_screen_width, (void), V_Subr0, DOC_screen_width) /*
::doc:screen_width::
screen-width
Returns the width of the root window or screen in pixels.
::end:: */
{
Window root;
int dummy1;
unsigned int dummy2;
int val;
if(XGetGeometry(x11_display, DefaultRootWindow(x11_display),
&root, &dummy1, &dummy1,
(unsigned int *)&val, &dummy2,
&dummy2, &dummy2))
return(make_number(val));
return(NULL);
}
_PR VALUE cmd_screen_height(void);
DEFUN("screen-height", cmd_screen_height, subr_screen_height, (void), V_Subr0, DOC_screen_height) /*
::doc:screen_height::
screen-height
Returns the height of the root window or screen in pixels.
::end:: */
{
Window root;
int dummy1;
unsigned int dummy2;
int val;
if(XGetGeometry(x11_display, DefaultRootWindow(x11_display),
&root, &dummy1, &dummy1,
&dummy2, (unsigned int *)&val,
&dummy2, &dummy2))
return(make_number(val));
return(NULL);
}
_PR VALUE cmd_window_left_edge(void);
DEFUN("window-left-edge", cmd_window_left_edge, subr_window_left_edge, (void), V_Subr0, DOC_window_left_edge) /*
::doc:window_left_edge::
window-left-edge
Returns the x position of the current window relative to the origin of the
root window or screen.
::end:: */
{
Window tmp;
int x, y;
if(XTranslateCoordinates(x11_display, curr_vw->vw_Window,
DefaultRootWindow(x11_display), 0, 0, &x, &y, &tmp))
return(make_number(x));
return(NULL);
}
_PR VALUE cmd_window_top_edge(void);
DEFUN("window-top-edge", cmd_window_top_edge, subr_window_top_edge, (void), V_Subr0, DOC_window_top_edge) /*
::doc:window_top_edge::
window-top-edge
Returns the y position of the current window relative to the origin of the
root window or screen.
::end:: */
{
Window tmp;
int x, y;
if(XTranslateCoordinates(x11_display, curr_vw->vw_Window,
DefaultRootWindow(x11_display), 0, 0, &x, &y, &tmp))
return(make_number(y));
return(NULL);
}
_PR VALUE cmd_window_width(void);
DEFUN("window-width", cmd_window_width, subr_window_width, (void), V_Subr0, DOC_window_width) /*
::doc:window_width::
window-width
Returns the width, in pixels, of the current window.
::end:: */
{
Window root;
int dummy1;
unsigned int dummy2;
int val;
if(XGetGeometry(x11_display, curr_vw->vw_Window,
&root, &dummy1, &dummy1,
(unsigned int *)&val, &dummy2,
&dummy2, &dummy2))
return(make_number(val));
return(NULL);
}
_PR VALUE cmd_window_height(void);
DEFUN("window-height", cmd_window_height, subr_window_height, (void), V_Subr0, DOC_window_height) /*
::doc:window_height::
window-height
Returns the height, in pixels, of the current window.
::end:: */
{
Window root;
int dummy1;
unsigned int dummy2;
int val;
if(XGetGeometry(x11_display, curr_vw->vw_Window,
&root, &dummy1, &dummy1,
&dummy2, (unsigned int *)&val,
&dummy2, &dummy2))
return(make_number(val));
return(NULL);
}
_PR VALUE cmd_window_bar_height(void);
DEFUN("window-bar-height", cmd_window_bar_height, subr_window_bar_height, (void), V_Subr0, DOC_window_bar_height) /*
::doc:window_bar_height::
window-bar-height
On an Amiga returns the number of pixels high the title bar of the window
is. This is 0 in X11.
::end:: */
{
return(make_number(0));
}
bool
sys_get_mouse_pos(POS *pos, VW *vw)
{
Window tmpw;
int tmp;
int x, y;
if(XQueryPointer(x11_display, vw->vw_Window, &tmpw, &tmpw, &tmp, &tmp, &x, &y, &tmp))
{
x = (x - vw->vw_XStartPix) / vw->vw_FontX;
y = (y - vw->vw_YStartPix) / vw->vw_FontY;
if((x < 0) || (y < 0) || (x >= vw->vw_MaxX) || (y >= vw->vw_MaxY))
return(FALSE);
pos->pos_Col = x + vw->vw_StartCol;
pos->pos_Line = y + vw->vw_StartLine;
if(pos->pos_Col < 0)
pos->pos_Col = 0;
if(pos->pos_Line < 0)
pos->pos_Line = 0;
if(pos->pos_Line >= vw->vw_Tx->tx_NumLines)
pos->pos_Line = vw->vw_Tx->tx_NumLines - 1;
pos->pos_Col = char_col(vw->vw_Tx, x + vw->vw_StartCol, pos->pos_Line);
return(TRUE);
}
return(FALSE);
}
_PR VALUE cmd_flush_output(void);
DEFUN("flush-output", cmd_flush_output, subr_flush_output, (void), V_Subr0, DOC_flush_output) /*
::doc:flush_output::
flush-output
Forces any cached window output to be drawn. This is usually unnecessary.
::end:: */
{
XFlush(x11_display);
return(sym_t);
}
void
sys_windows_init(void)
{
ADD_SUBR(subr_set_font);
ADD_SUBR(subr_screen_width);
ADD_SUBR(subr_screen_height);
ADD_SUBR(subr_window_left_edge);
ADD_SUBR(subr_window_top_edge);
ADD_SUBR(subr_window_width);
ADD_SUBR(subr_window_height);
ADD_SUBR(subr_window_bar_height);
ADD_SUBR(subr_flush_output);
}